#!/usr/bin/env bash

# Note this file was copied from https://github.com/junegunn/fzf/blob/master/install
# and modified for this project but it's original license and copyright
# are still credited to the original author.

# The MIT License (MIT)
#
# Copyright (c) 2013-2020 Junegunn Choi
# Copyright (c) 2020 slim-bean
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

set -u

version=2.0.0
auto_completion=
update_config=2
binary_arch=
shells="bash zsh"
prefix='~/.loki-shell'
prefix_expand=~/.loki-shell
fish_dir=${XDG_CONFIG_HOME:-$HOME/.config}/fish
docker_tag="grafana/loki:$version"
binary_only=0

help() {
  cat << EOF
usage: $0 [OPTIONS]

    --help               Show this message
    --bin                Download binaries only
    --[no-]key-bindings  Enable/disable key bindings (CTRL-T, CTRL-R, ALT-C)
    --[no-]completion    Enable/disable fuzzy completion (bash & zsh)
    --[no-]update-rc     Whether or not to update shell configuration files

    --no-bash            Do not set up bash configuration
    --no-zsh             Do not set up zsh configuration
    --no-fish            Do not set up fish configuration

    --docker-tag         Specify an exact docker image to use for Loki e.g. --docker-tag=grafana/loki:1.6.1
EOF
}

while test $# -gt 0; do
  case $1 in
    --help)
      help
      exit 0
      ;;
    --update-rc)
      update_config=1
      shift
      ;;
    --no-update-rc)
      update_config=0
      shift
      ;;
    --bin)
      binary_only=1
      shift
      ;;
    --no-bash)
      shells=${shells/bash/}
      shift
      ;;
    --no-zsh)
      shells=${shells/zsh/}
      shift
      ;;
    --no-fish)
      shells=${shells/fish/}
      shift
      ;;
    --docker-tag*)
      docker_tag=$(echo $1 | sed -e 's/^[^=]*=//g')
      shift
      ;;
    *)
      echo "unknown option: $opt"
      help
      exit 1
      ;;
  esac
done

cd "$(dirname "${BASH_SOURCE[0]}")"
loki_shell_base=$(pwd)
loki_shell_base_esc=$(printf %q "$loki_shell_base")

# make some directories
mkdir -p "$loki_shell_base"/data
mkdir -p "$loki_shell_base"/config
mkdir -p "$loki_shell_base"/bin

# check for stdbuf
if ! hash stdbuf 2>/dev/null; then
    if ! hash gstdbuf 2>/dev/null; then
      echo 'loki-shell requires either stdbuf or gstdbuf to be installed and on the path'
      echo 'install the coreutils package and re-run this install script (brew install coreutils)'
      exit 1
    fi
fi

ask() {
  while true; do
    read -p "$1 ([y]/n) " -r
    REPLY=${REPLY:-"y"}
    if [[ $REPLY =~ ^[Yy]$ ]]; then
      return 1
    elif [[ $REPLY =~ ^[Nn]$ ]]; then
      return 0
    fi
  done
}

prompt() {
  read -p "$1 (press enter to continue) " -r
}

prompt_string() {
  read -p "$1 ($2) " -r
  REPLY=${REPLY:-"$2"}
  echo $REPLY
}

check_binary() {
  echo -n "  - Checking ${1} executable ... "
  local output
  output=$("$loki_shell_base"/bin/${1} --version 2>&1)
  if [ $? -ne 0 ]; then
    echo "Error: $output"
    binary_error="Invalid binary"
  else
    if [[ $output != *"$version"* ]]; then
      echo "output did not contain correct version $version: $output"
      binary_error="Invalid version"
    else
      echo "$output"
      binary_error=""
      return 0
    fi
  fi
  rm -f "$loki_shell_base"/bin/${1}
  return 1
}

try_curl() {
  command -v curl > /dev/null &&
  if [[ $1 =~ tgz$ ]]; then
    curl -fL $1 | tar -xzf -
  else
    local temp=${TMPDIR:-/tmp}/temp.zip
    curl -fLo "$temp" $1 && unzip -o "$temp" && rm -f "$temp"
  fi
}

try_wget() {
  command -v wget > /dev/null &&
  if [[ $1 =~ tgz$ ]]; then
    wget -O - $1 | tar -xzf -
  else
    local temp=${TMPDIR:-/tmp}/${1}.zip
    wget -O "$temp" $1 && unzip -o "$temp" && rm -f "$temp"
  fi
}

download() {
  echo "Downloading ${1}"

  if [ -x "$loki_shell_base"/bin/"${1}" ]; then
    echo "  - Already exists"
    check_binary ${1} && return
  fi

  mkdir -p "$loki_shell_base"/bin && cd "$loki_shell_base"/bin
  if [ $? -ne 0 ]; then
    binary_error="Failed to create bin directory"
    return
  fi

  local url
  url=https://github.com/grafana/loki/releases/download/v$version/${2}

  set -o pipefail
  if ! (try_curl $url || try_wget $url); then
    set +o pipefail
    binary_error="Failed to download with curl and wget"
    return
  fi
  set +o pipefail

  mv *${1}* ${1}

  if [ ! -f ${1} ]; then
    binary_error="Failed to download ${1}"
    return
  fi

  chmod +x ${1} && check_binary ${1}
}

# Try to download binary executable
archi=$(uname -sm)
binary_available=1
binary_error=""
case "$archi" in
  Darwin\ *64)
    download promtail promtail-darwin-${binary_arch:-amd64}.zip
    download logcli logcli-darwin-${binary_arch:-amd64}.zip
    download loki loki-darwin-${binary_arch:-amd64}.zip
    ;;
  Linux\ armv7*)
    download promtail promtail-linux-${binary_arch:-arm}.zip
    download logcli logcli-linux-${binary_arch:-arm}.zip
    download loki loki-linux-${binary_arch:-arm}.zip
    ;;
  Linux\ armv8*)
    download promtail promtail-linux-${binary_arch:-arm64}.zip
    download logcli logcli-linux-${binary_arch:-arm64}.zip
    download loki loki-linux-${binary_arch:-arm64}.zip
    ;;
  Linux\ aarch64*)
    download promtail promtail-linux-${binary_arch:-arm64}.zip
    download logcli logcli-linux-${binary_arch:-arm64}.zip
    download loki loki-linux-${binary_arch:-arm64}.zip
    ;;
  Linux\ *64)
    download promtail promtail-linux-${binary_arch:-amd64}.zip
    download logcli logcli-linux-${binary_arch:-amd64}.zip
    download loki loki-linux-${binary_arch:-amd64}.zip
    ;;
  OpenBSD\ *64)
    download promtail promtail-freebsd-${binary_arch:-amd64}.zip
    download logcli logcli-freebsd-${binary_arch:-amd64}.zip
    download loki loki-freebsd-${binary_arch:-amd64}.zip
    ;;
  *)             binary_available=0 binary_error=1 ;;
esac

[[ ${binary_only} -eq 1 ]] && exit 0

for s in $shells; do
  if ! command -v "$s" > /dev/null; then
    shells=${shells/$s/}
  fi
done

if [[ ${#shells} -lt 3 ]]; then
  echo "No shell configuration to be updated."
  exit 0
fi

append_line() {
  set -e

  local update line file pat lno
  update="$1"
  line="$2"
  file="$3"
  pat="${4:-}"
  lno=""

  echo "Update $file:"
  echo "  - $line"
  if [ -f "$file" ]; then
    if [ $# -lt 4 ]; then
      lno=$(\grep -nF "$line" "$file" | sed 's/:.*//' | tr '\n' ' ')
    else
      lno=$(\grep -nF "$pat" "$file" | sed 's/:.*//' | tr '\n' ' ')
    fi
  fi
  if [ -n "$lno" ]; then
    echo "    - Already exists: line #$lno"
  else
    if [ $update -eq 1 ]; then
      [ -f "$file" ] && echo >> "$file"
      echo "$line" >> "$file"
      echo "    + Added"
    else
      echo "    ~ Skipped"
    fi
  fi
  echo
  set +e
}

# Install Loki

echo
ask "Do you want to install Loki?"
install_loki=$?

if [ $install_loki -eq 1 ]; then
  ## Ask docker or binary
  echo
  ask "[y] to run Loki in Docker, [n] to run Loki as a binary"
  docker=$?
  if [ $docker -eq 1 ]; then
    if [ -f "$loki_shell_base"/config/loki-docker-config.yaml ]; then
      echo
      echo "Existing config file found at $loki_shell_base/.loki-shell/config/loki-docker-config.yaml"
      prompt "File will not be modified"
    else
      cp "$loki_shell_base"/cfg-template/loki-docker-local-config.yaml "$loki_shell_base"/config/loki-docker-config.yaml
    fi

    docker inspect loki-shell | grep -q "$docker_tag"
    if [ $? -ne 0 ]; then
      docker stop loki-shell || true
      docker rm loki-shell || true
      docker run -d --restart=unless-stopped --name=loki-shell --user "$(id -u)":"$(id -g)" --mount type=bind,source="$loki_shell_base"/config/loki-docker-config.yaml,target=/etc/loki/local-config.yaml --mount type=bind,source="$loki_shell_base"/data,target=/loki -p 4100:4100 "$docker_tag"
    else
      echo "loki-shell docker image already running at correct version"
    fi
  else
    if [ -f "$loki_shell_base"/config/loki-binary-config.yaml ]; then
      echo
      echo "Existing config file found at $loki_shell_base/.loki-shell/config/loki-binary-config.yaml"
      prompt "File will not be modified"
    else
      cp "$loki_shell_base"/cfg-template/loki-local-config.yaml "$loki_shell_base"/config/loki-binary-config.yaml
      sed -i.bak "s|FIXME|$loki_shell_base|g" "$loki_shell_base"/config/loki-binary-config.yaml
    fi
    echo
    ask "Run Loki with systemd?"
    systemd=$?
    if [ $systemd -eq 1 ]; then
      cp "$loki_shell_base"/cfg-template/loki-shell.service "$loki_shell_base"/config/loki-shell.service
      sed -i.bak "s|FIXME|$loki_shell_base|g" "$loki_shell_base"/config/loki-shell.service
      sed -i.bak "s|USER|$USER|g" "$loki_shell_base"/config/loki-shell.service
      echo
      echo "Installing the systemd service requires root permissions."
      ask "[y] to run these commands with sudo [n] to print out the commands and you can run them yourself."
      run_sudo_cmds=$?
      if [ $run_sudo_cmds -eq 1 ]; then
        sudo cp $loki_shell_base/config/loki-shell.service /etc/systemd/system/loki-shell.service
        sudo systemctl daemon-reload
        sudo systemctl enable loki-shell
        sudo systemctl start loki-shell
      else
        echo "sudo cp $loki_shell_base/config/loki-shell.service /etc/systemd/system/loki-shell.service"
        echo "sudo systemctl daemon-reload"
        echo "sudo systemctl enable loki-shell"
        echo "sudo systemctl start loki-shell"
        prompt "Copy these commands and run them when the script finishes."
      fi
    else
      echo
      echo "This is as far as this script can take you"
      echo "You will need to setup an auto-start for Loki"
      echo "It can be run with this command: $loki_shell_base/bin/loki -config.file=$loki_shell_base/config/loki-binary-config.yaml"
      prompt ""
    fi
  fi
fi



if [ $update_config -eq 2 ]; then
  # The script used to ask if you wanted to update shell files, I removed this so set this var to the value of "yes"
  update_config=1

  default_host="http://localhost:4100"
  echo
  loki_host=$(prompt_string "Enter the URL for your Loki server or press enter for default" "$default_host")
  if [ -f "$loki_shell_base"/config/promtail-logging-config.yaml ]; then
    echo "Existing promtail config file found at $loki_shell_base/.loki-shell/config/promtail-logging-config.yaml"
    prompt "File will not be modified"
  else
    cp "$loki_shell_base"/cfg-template/promtail-logging-config.yaml "$loki_shell_base"/config/promtail-logging-config.yaml
    sed -i.bak "s|HOST|$loki_host|g" "$loki_shell_base"/config/promtail-logging-config.yaml
  fi
fi
echo
for shell in $shells; do
  [ $shell = zsh ] && dest=${ZDOTDIR:-~}/.zshrc || dest=~/.bashrc
  append_line $update_config "############## BEGIN LOKI-SHELL #####################" "$dest"
  append_line $update_config "# NOTE when changing the Loki URL, also remember to change the promtail config: ~/.loki-shell/config/promtail-logging-config.yaml" "$dest"
  append_line $update_config "export LOKI_URL=\"$loki_host\"" "$dest" "export LOKI_URL"
  append_line $update_config "[ -f ${prefix}/shell/loki-shell.${shell} ] && source ${prefix}/shell/loki-shell.${shell}" "$dest" "${prefix}/shell/loki-shell.${shell}"
  append_line $update_config "############## END LOKI-SHELL   #####################" "$dest"
done


if [ $update_config -eq 1 ]; then
  echo 'Finished. Restart your shell or reload config file.'
  if [[ "$shells" =~ bash ]]; then
    echo -n '   source ~/.bashrc  # bash'
    [[ "$archi" =~ Darwin ]] && echo -n '  (.bashrc should be loaded from .bash_profile)'
    echo
  fi
  [[ "$shells" =~ zsh ]]  && echo "   source ${ZDOTDIR:-~}/.zshrc   # zsh"
  echo
  echo 'Use uninstall script to remove loki-shell.'
  echo
fi
